// Check the DB Node Config and privilege is right.
package main

import (
	"bytes"
	"database/sql"
	"fmt"
	"io/ioutil"
	"os"

	"github.com/BurntSushi/toml"
	_ "github.com/go-sql-driver/mysql"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "Epg Proxy Checker"
	app.Usage = "Check the epg service node, account privilege"
	app.Version = "0.0.3"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "task,t", Value: "node", Usage: "Task Name",
		},
		cli.StringFlag{
			Name: "addr,a", Value: "127.0.0.1:6603", Usage: "Epg Proxy Addr<host:port>",
		},
		cli.StringFlag{
			Name: "config,c", Value: "./checklist.toml", Usage: "Check list toml file.",
		},
	}
	app.Action = handle
	app.Run(os.Args)

}

func handle(ctx *cli.Context) error {
	if _check == nil {
		ck := &Check{
			accounts: make([]Account, 0, 10),
		}
		ck.parseConfig(ctx.String("c"))
		_check = ck
	}

	task := ctx.String("t")
	switch task {
	case "":
	case "node":
		fallthrough
	default:
		_check.checkNode(ctx)
	}
	return nil
}

var _check *Check

//Check the check.
type Check struct {
	db       *sql.DB
	accounts []Account
}

type Account struct {
	Name      string
	Passwd    string
	Databases []string
}

func (c *Check) checkNode(ctx *cli.Context) {
	addr := ctx.String("a")
	for _, acc := range c.accounts {
		for _, db := range acc.Databases {
			err := checkDB(fmt.Sprintf("%s:%s@tcp(%s)/%s", acc.Name, acc.Passwd, addr, db))
			rst := "[OK]"
			if err != nil {
				rst = fmt.Sprintf("[FAILD] %v", err)
			}
			fmt.Printf("user:%s	passwd:%s	db:%s	%s\n", acc.Name, acc.Passwd, db, rst)
		}
	}
}

func checkDB(dsn string) error {
	// fmt.Println(dsn)
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		return err
	}
	defer db.Close()

	row := db.QueryRow("SELECT 1")
	var one int
	if err := row.Scan(&one); err != nil {
		return err
	}
	return nil
}

func (c *Check) parseConfig(f string) {
	content, err := ioutil.ReadFile(f)
	if err != nil {
		fmt.Printf("Parse file:%v error\n", f)
		os.Exit(-2)
	}
	accounts := make(map[string][]Account)
	if err := toml.Unmarshal(content, &accounts); err != nil {
		fmt.Printf("Parse content error: %v\n--------\n%v", err, string(content))
		os.Exit(-3)
	}
	c.accounts = accounts["account"]
	// fmt.Printf("accounts:%v", c.accounts)
}

func encodeConfig() {
	acc := make([]Account, 0, 4)
	for i := 0; i < 4; i++ {
		acc = append(acc, Account{
			Name:      fmt.Sprintf("name_%d", i),
			Passwd:    "pass",
			Databases: []string{"11", "22"},
		})
	}
	content := make(map[string][]Account)
	content["account"] = acc
	buf := new(bytes.Buffer)
	if err := toml.NewEncoder(buf).Encode(content); err != nil {
		fmt.Printf("Parse content error: %v", err)
		os.Exit(-3)
	}
	fmt.Println(buf.String())
}
